package git.soulbgm.hdfs.config;

import git.soulbgm.hdfs.aspect.HdfsPoolAspect;
import git.soulbgm.hdfs.common.HdfsClient;
import git.soulbgm.hdfs.common.HdfsFactory;
import git.soulbgm.hdfs.common.HdfsPool;
import git.soulbgm.hdfs.common.HdfsTool;
import git.soulbgm.hdfs.properties.HdfsProperties;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;

/**
 * HDFS工具自动配置类
 *
 * @author SoulBGM
 * @date 2022/06/29 11:04
 */
@Configuration
@EnableConfigurationProperties({HdfsProperties.class})
public class HdfsToolAutoConfiguration {

    private static final Logger log = LoggerFactory.getLogger(HdfsToolAutoConfiguration.class);

    private HdfsPool pool;

    @Bean
    @ConditionalOnClass({HdfsFactory.class})
    public synchronized HdfsPool hdfsPool(HdfsProperties hdfsProperties) {
        HdfsFactory hdfsFactory = new HdfsFactory(hdfsProperties);
        //设置对象池的相关参数
        GenericObjectPoolConfig<HdfsClient> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxIdle(hdfsProperties.getMaxIdle());
        poolConfig.setMaxTotal(hdfsProperties.getMaxTotal());
        poolConfig.setMinIdle(hdfsProperties.getMinIdle());
        poolConfig.setBlockWhenExhausted(true);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setTimeBetweenEvictionRunsMillis(0X1b7740L);
        //一定要关闭jmx，不然springboot启动会报已经注册了某个jmx的错误
        poolConfig.setJmxEnabled(false);

        //新建一个对象池,传入对象工厂和配置
        HdfsPool pool = new HdfsPool(hdfsFactory, poolConfig);

        int size = initPool(pool, hdfsProperties.getInitialSize(), hdfsProperties.getMaxIdle());
        log.info("初始化HDFS对象池完成，初始HdfsClient数量是" + size);
        return this.pool = pool;
    }

    @Bean
    public HdfsTool hdfsTool(HdfsPool pool) {
        return new HdfsTool(pool);
    }

    @Bean
    public HdfsPoolAspect hdfsPoolAspect(HdfsPool pool) {
        return new HdfsPoolAspect(pool);
    }

    /**
     * 预先加载testObject对象到对象池中
     *
     * @param initialSize 初始化连接数
     * @param maxIdle     最大空闲连接数
     */
    private int initPool(HdfsPool pool, int initialSize, int maxIdle) {
        if (initialSize <= 0) {
            return 0;
        }
        int size = Math.min(initialSize, maxIdle);
        for (int i = 0; i < size; i++) {
            try {
                pool.addObject();
            } catch (Exception e) {
                log.error("初始化HDFS对象池异常", e);
                throw new RuntimeException(e);
            }
        }
        return size;
    }

    /**
     * 销毁对象池
     */
    @PreDestroy
    public void destroy() {
        if (pool != null) {
            pool.close();
            log.info("销毁对象池");
        }
    }

}
